#ifndef __H_SAFEQUEUE__
#define __H_SAFEQUEUE__

#include <list>
#include <algorithm>

namespace bl{


	template<typename TItemType>
	class SafeQueue
	{
	public:
		SafeQueue(int limit)
		{
			handles_[StopperIndex] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
			handles_[SemaphoreIndex] = ::CreateSemaphore(NULL, 0, limit, NULL);
		}

		virtual ~SafeQueue()
		{
			::CloseHandle(handles_[StopperIndex]);
			::CloseHandle(handles_[SemaphoreIndex]);
		}

		bool Push(TItemType item)
		{
			bool ret = false;
			bl::AutoLockCS lock(crit_sec_);
			list_.push_back(item);
			ret = (TRUE == ::ReleaseSemaphore(handles_[SemaphoreIndex], 1, NULL));
			if(!ret)
			{
				list_.pop_back();
			}

			return ret;
		}

		bool Pop(TItemType* val, long timeOut=INFINITE)
		{
			DWORD ret = ::WaitForMultipleObjects(TotalIndex, handles_, FALSE, timeOut);
			switch(ret)
			{
			case StopperIndex:
				return false;
			case SemaphoreIndex:
				{
					bl::AutoLockCS lock(crit_sec_);
					*val = list_.front();
					list_.pop_front();
					return true;
				}
			case WAIT_TIMEOUT:
				return false;
			}
			assert(false);
			return false;
		}

		bool Remove(TItemType item)
		{
			bl::AutoLockCS lock(crit_sec_);
			if(WAIT_OBJECT_0 == WaitForSingleObject(handles_[SemaphoreIndex], 0))
			{
				std::list<TItemType>::iterator ite = std::find(list_.begin(), list_.end(), item);

				if (ite != list_.end())
				{
					list_.erase(ite);
					return true;
				} 
				else
				{
					::ReleaseSemaphore(handles_[SemaphoreIndex], 1, NULL);
				}
			}
			
			return false;
		}

		void Shutdown()
		{
			::SetEvent(handles_[StopperIndex]);
		}

	protected:
		std::list<TItemType> list_;
		bl::CritSec crit_sec_;

	private:
		enum {StopperIndex = 0, SemaphoreIndex, TotalIndex};
		HANDLE handles_[TotalIndex];
	};


}



#endif